home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / include / asm-m32r / local.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  8.8 KB  |  367 lines

  1. #ifndef __M32R_LOCAL_H
  2. #define __M32R_LOCAL_H
  3.  
  4. /*
  5.  *  linux/include/asm-m32r/local.h
  6.  *
  7.  *  M32R version:
  8.  *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  9.  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  10.  *    Copyright (C) 2007  Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
  11.  */
  12.  
  13. #include <linux/percpu.h>
  14. #include <asm/assembler.h>
  15. #include <asm/system.h>
  16. #include <asm/local.h>
  17.  
  18. /*
  19.  * Atomic operations that C can't guarantee us.  Useful for
  20.  * resource counting etc..
  21.  */
  22.  
  23. /*
  24.  * Make sure gcc doesn't try to be clever and move things around
  25.  * on us. We need to use _exactly_ the address the user gave us,
  26.  * not some alias that contains the same information.
  27.  */
  28. typedef struct { volatile int counter; } local_t;
  29.  
  30. #define LOCAL_INIT(i)    { (i) }
  31.  
  32. /**
  33.  * local_read - read local variable
  34.  * @l: pointer of type local_t
  35.  *
  36.  * Atomically reads the value of @l.
  37.  */
  38. #define local_read(l)    ((l)->counter)
  39.  
  40. /**
  41.  * local_set - set local variable
  42.  * @l: pointer of type local_t
  43.  * @i: required value
  44.  *
  45.  * Atomically sets the value of @l to @i.
  46.  */
  47. #define local_set(l, i)    (((l)->counter) = (i))
  48.  
  49. /**
  50.  * local_add_return - add long to local variable and return it
  51.  * @i: long value to add
  52.  * @l: pointer of type local_t
  53.  *
  54.  * Atomically adds @i to @l and return (@i + @l).
  55.  */
  56. static inline long local_add_return(long i, local_t *l)
  57. {
  58.     unsigned long flags;
  59.     long result;
  60.  
  61.     local_irq_save(flags);
  62.     __asm__ __volatile__ (
  63.         "# local_add_return        \n\t"
  64.         DCACHE_CLEAR("%0", "r4", "%1")
  65.         "ld %0, @%1;            \n\t"
  66.         "add    %0, %2;            \n\t"
  67.         "st %0, @%1;            \n\t"
  68.         : "=&r" (result)
  69.         : "r" (&l->counter), "r" (i)
  70.         : "memory"
  71. #ifdef CONFIG_CHIP_M32700_TS1
  72.         , "r4"
  73. #endif    /* CONFIG_CHIP_M32700_TS1 */
  74.     );
  75.     local_irq_restore(flags);
  76.  
  77.     return result;
  78. }
  79.  
  80. /**
  81.  * local_sub_return - subtract long from local variable and return it
  82.  * @i: long value to subtract
  83.  * @l: pointer of type local_t
  84.  *
  85.  * Atomically subtracts @i from @l and return (@l - @i).
  86.  */
  87. static inline long local_sub_return(long i, local_t *l)
  88. {
  89.     unsigned long flags;
  90.     long result;
  91.  
  92.     local_irq_save(flags);
  93.     __asm__ __volatile__ (
  94.         "# local_sub_return        \n\t"
  95.         DCACHE_CLEAR("%0", "r4", "%1")
  96.         "ld %0, @%1;            \n\t"
  97.         "sub    %0, %2;            \n\t"
  98.         "st %0, @%1;            \n\t"
  99.         : "=&r" (result)
  100.         : "r" (&l->counter), "r" (i)
  101.         : "memory"
  102. #ifdef CONFIG_CHIP_M32700_TS1
  103.         , "r4"
  104. #endif    /* CONFIG_CHIP_M32700_TS1 */
  105.     );
  106.     local_irq_restore(flags);
  107.  
  108.     return result;
  109. }
  110.  
  111. /**
  112.  * local_add - add long to local variable
  113.  * @i: long value to add
  114.  * @l: pointer of type local_t
  115.  *
  116.  * Atomically adds @i to @l.
  117.  */
  118. #define local_add(i, l) ((void) local_add_return((i), (l)))
  119.  
  120. /**
  121.  * local_sub - subtract the local variable
  122.  * @i: long value to subtract
  123.  * @l: pointer of type local_t
  124.  *
  125.  * Atomically subtracts @i from @l.
  126.  */
  127. #define local_sub(i, l) ((void) local_sub_return((i), (l)))
  128.  
  129. /**
  130.  * local_sub_and_test - subtract value from variable and test result
  131.  * @i: integer value to subtract
  132.  * @l: pointer of type local_t
  133.  *
  134.  * Atomically subtracts @i from @l and returns
  135.  * true if the result is zero, or false for all
  136.  * other cases.
  137.  */
  138. #define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0)
  139.  
  140. /**
  141.  * local_inc_return - increment local variable and return it
  142.  * @l: pointer of type local_t
  143.  *
  144.  * Atomically increments @l by 1 and returns the result.
  145.  */
  146. static inline long local_inc_return(local_t *l)
  147. {
  148.     unsigned long flags;
  149.     long result;
  150.  
  151.     local_irq_save(flags);
  152.     __asm__ __volatile__ (
  153.         "# local_inc_return        \n\t"
  154.         DCACHE_CLEAR("%0", "r4", "%1")
  155.         "ld %0, @%1;            \n\t"
  156.         "addi    %0, #1;            \n\t"
  157.         "st %0, @%1;            \n\t"
  158.         : "=&r" (result)
  159.         : "r" (&l->counter)
  160.         : "memory"
  161. #ifdef CONFIG_CHIP_M32700_TS1
  162.         , "r4"
  163. #endif    /* CONFIG_CHIP_M32700_TS1 */
  164.     );
  165.     local_irq_restore(flags);
  166.  
  167.     return result;
  168. }
  169.  
  170. /**
  171.  * local_dec_return - decrement local variable and return it
  172.  * @l: pointer of type local_t
  173.  *
  174.  * Atomically decrements @l by 1 and returns the result.
  175.  */
  176. static inline long local_dec_return(local_t *l)
  177. {
  178.     unsigned long flags;
  179.     long result;
  180.  
  181.     local_irq_save(flags);
  182.     __asm__ __volatile__ (
  183.         "# local_dec_return        \n\t"
  184.         DCACHE_CLEAR("%0", "r4", "%1")
  185.         "ld %0, @%1;            \n\t"
  186.         "addi    %0, #-1;        \n\t"
  187.         "st %0, @%1;            \n\t"
  188.         : "=&r" (result)
  189.         : "r" (&l->counter)
  190.         : "memory"
  191. #ifdef CONFIG_CHIP_M32700_TS1
  192.         , "r4"
  193. #endif    /* CONFIG_CHIP_M32700_TS1 */
  194.     );
  195.     local_irq_restore(flags);
  196.  
  197.     return result;
  198. }
  199.  
  200. /**
  201.  * local_inc - increment local variable
  202.  * @l: pointer of type local_t
  203.  *
  204.  * Atomically increments @l by 1.
  205.  */
  206. #define local_inc(l) ((void)local_inc_return(l))
  207.  
  208. /**
  209.  * local_dec - decrement local variable
  210.  * @l: pointer of type local_t
  211.  *
  212.  * Atomically decrements @l by 1.
  213.  */
  214. #define local_dec(l) ((void)local_dec_return(l))
  215.  
  216. /**
  217.  * local_inc_and_test - increment and test
  218.  * @l: pointer of type local_t
  219.  *
  220.  * Atomically increments @l by 1
  221.  * and returns true if the result is zero, or false for all
  222.  * other cases.
  223.  */
  224. #define local_inc_and_test(l) (local_inc_return(l) == 0)
  225.  
  226. /**
  227.  * local_dec_and_test - decrement and test
  228.  * @l: pointer of type local_t
  229.  *
  230.  * Atomically decrements @l by 1 and
  231.  * returns true if the result is 0, or false for all
  232.  * other cases.
  233.  */
  234. #define local_dec_and_test(l) (local_dec_return(l) == 0)
  235.  
  236. /**
  237.  * local_add_negative - add and test if negative
  238.  * @l: pointer of type local_t
  239.  * @i: integer value to add
  240.  *
  241.  * Atomically adds @i to @l and returns true
  242.  * if the result is negative, or false when
  243.  * result is greater than or equal to zero.
  244.  */
  245. #define local_add_negative(i, l) (local_add_return((i), (l)) < 0)
  246.  
  247. #define local_cmpxchg(l, o, n) (cmpxchg_local(&((l)->counter), (o), (n)))
  248. #define local_xchg(v, new) (xchg_local(&((l)->counter), new))
  249.  
  250. /**
  251.  * local_add_unless - add unless the number is a given value
  252.  * @l: pointer of type local_t
  253.  * @a: the amount to add to l...
  254.  * @u: ...unless l is equal to u.
  255.  *
  256.  * Atomically adds @a to @l, so long as it was not @u.
  257.  * Returns non-zero if @l was not @u, and zero otherwise.
  258.  */
  259. static inline int local_add_unless(local_t *l, long a, long u)
  260. {
  261.     long c, old;
  262.     c = local_read(l);
  263.     for (;;) {
  264.         if (unlikely(c == (u)))
  265.             break;
  266.         old = local_cmpxchg((l), c, c + (a));
  267.         if (likely(old == c))
  268.             break;
  269.         c = old;
  270.     }
  271.     return c != (u);
  272. }
  273.  
  274. #define local_inc_not_zero(l) local_add_unless((l), 1, 0)
  275.  
  276. static inline void local_clear_mask(unsigned long  mask, local_t *addr)
  277. {
  278.     unsigned long flags;
  279.     unsigned long tmp;
  280.  
  281.     local_irq_save(flags);
  282.     __asm__ __volatile__ (
  283.         "# local_clear_mask        \n\t"
  284.         DCACHE_CLEAR("%0", "r5", "%1")
  285.         "ld %0, @%1;            \n\t"
  286.         "and    %0, %2;            \n\t"
  287.         "st %0, @%1;            \n\t"
  288.         : "=&r" (tmp)
  289.         : "r" (addr), "r" (~mask)
  290.         : "memory"
  291. #ifdef CONFIG_CHIP_M32700_TS1
  292.         , "r5"
  293. #endif    /* CONFIG_CHIP_M32700_TS1 */
  294.     );
  295.     local_irq_restore(flags);
  296. }
  297.  
  298. static inline void local_set_mask(unsigned long  mask, local_t *addr)
  299. {
  300.     unsigned long flags;
  301.     unsigned long tmp;
  302.  
  303.     local_irq_save(flags);
  304.     __asm__ __volatile__ (
  305.         "# local_set_mask        \n\t"
  306.         DCACHE_CLEAR("%0", "r5", "%1")
  307.         "ld %0, @%1;            \n\t"
  308.         "or    %0, %2;            \n\t"
  309.         "st %0, @%1;            \n\t"
  310.         : "=&r" (tmp)
  311.         : "r" (addr), "r" (mask)
  312.         : "memory"
  313. #ifdef CONFIG_CHIP_M32700_TS1
  314.         , "r5"
  315. #endif    /* CONFIG_CHIP_M32700_TS1 */
  316.     );
  317.     local_irq_restore(flags);
  318. }
  319.  
  320. /* Atomic operations are already serializing on m32r */
  321. #define smp_mb__before_local_dec()    barrier()
  322. #define smp_mb__after_local_dec()    barrier()
  323. #define smp_mb__before_local_inc()    barrier()
  324. #define smp_mb__after_local_inc()    barrier()
  325.  
  326. /* Use these for per-cpu local_t variables: on some archs they are
  327.  * much more efficient than these naive implementations.  Note they take
  328.  * a variable, not an address.
  329.  */
  330.  
  331. #define __local_inc(l)        ((l)->a.counter++)
  332. #define __local_dec(l)        ((l)->a.counter++)
  333. #define __local_add(i, l)    ((l)->a.counter += (i))
  334. #define __local_sub(i, l)    ((l)->a.counter -= (i))
  335.  
  336. /* Use these for per-cpu local_t variables: on some archs they are
  337.  * much more efficient than these naive implementations.  Note they take
  338.  * a variable, not an address.
  339.  */
  340.  
  341. /* Need to disable preemption for the cpu local counters otherwise we could
  342.    still access a variable of a previous CPU in a non local way. */
  343. #define cpu_local_wrap_v(l)         \
  344.     ({ local_t res__;        \
  345.        preempt_disable();         \
  346.        res__ = (l);            \
  347.        preempt_enable();        \
  348.        res__; })
  349. #define cpu_local_wrap(l)        \
  350.     ({ preempt_disable();        \
  351.        l;                \
  352.        preempt_enable(); })        \
  353.  
  354. #define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
  355. #define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
  356. #define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
  357. #define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
  358. #define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
  359. #define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
  360.  
  361. #define __cpu_local_inc(l)    cpu_local_inc(l)
  362. #define __cpu_local_dec(l)    cpu_local_dec(l)
  363. #define __cpu_local_add(i, l)    cpu_local_add((i), (l))
  364. #define __cpu_local_sub(i, l)    cpu_local_sub((i), (l))
  365.  
  366. #endif /* __M32R_LOCAL_H */
  367.